window: Introduce actions for window buttons
authorAlexander Mikhaylenko <alexm@gnome.org>
Wed, 22 Apr 2020 17:32:10 +0000 (22:32 +0500)
committerAlexander Mikhaylenko <alexm@gnome.org>
Wed, 22 Apr 2020 18:01:12 +0000 (23:01 +0500)
Add the following actions:
 * window.close
 * window.toggle-maximize
 * window.minimize

Ensure they are disabled when not appropriate, such as for modal windows.

Use them in GtkHeaderBar.

gtk/gtkheaderbar.c
gtk/gtkwindow.c

index 90fc5be4193603bdd2f407a9f229f1859cca5c55..1c540d2f4ba818f476059a26aa13adcc8e052b3c 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "gtkheaderbarprivate.h"
 
+#include "gtkactionable.h"
 #include "gtkbox.h"
 #include "gtkbutton.h"
 #include "gtkbuildable.h"
@@ -375,8 +376,8 @@ _gtk_header_bar_update_window_buttons (GtkHeaderBar *bar)
                   g_object_set (image, "use-fallback", TRUE, NULL);
                   gtk_container_add (GTK_CONTAINER (button), image);
                   gtk_widget_set_can_focus (button, FALSE);
-                  g_signal_connect_swapped (button, "clicked",
-                                            G_CALLBACK (gtk_window_minimize), window);
+                  gtk_actionable_set_action_name (GTK_ACTIONABLE (button),
+                                                  "window.minimize");
 
                   accessible = gtk_widget_get_accessible (button);
                   if (GTK_IS_ACCESSIBLE (accessible))
@@ -398,8 +399,8 @@ _gtk_header_bar_update_window_buttons (GtkHeaderBar *bar)
                   g_object_set (image, "use-fallback", TRUE, NULL);
                   gtk_container_add (GTK_CONTAINER (button), image);
                   gtk_widget_set_can_focus (button, FALSE);
-                  g_signal_connect_swapped (button, "clicked",
-                                            G_CALLBACK (_gtk_window_toggle_maximized), window);
+                  gtk_actionable_set_action_name (GTK_ACTIONABLE (button),
+                                                  "window.toggle-maximized");
 
                   accessible = gtk_widget_get_accessible (button);
                   if (GTK_IS_ACCESSIBLE (accessible))
@@ -416,8 +417,8 @@ _gtk_header_bar_update_window_buttons (GtkHeaderBar *bar)
                   g_object_set (image, "use-fallback", TRUE, NULL);
                   gtk_container_add (GTK_CONTAINER (button), image);
                   gtk_widget_set_can_focus (button, FALSE);
-                  g_signal_connect_swapped (button, "clicked",
-                                            G_CALLBACK (gtk_window_close), window);
+                  gtk_actionable_set_action_name (GTK_ACTIONABLE (button),
+                                                  "window.close");
 
                   accessible = gtk_widget_get_accessible (button);
                   if (GTK_IS_ACCESSIBLE (accessible))
index a131300ce35cbebe94062bc3615c598ab2042a7d..0abba8d1e751653ce5cbefcaf9989fde3f56fb18 100644 (file)
@@ -27,6 +27,7 @@
 #include "gtkwindowprivate.h"
 
 #include "gtkaccelgroupprivate.h"
+#include "gtkactionable.h"
 #include "gtkapplicationprivate.h"
 #include "gtkbox.h"
 #include "gtkbuildable.h"
@@ -460,7 +461,7 @@ static GList   *icon_list_from_theme                  (GtkWindow    *window,
                                                       const gchar  *name);
 static void     gtk_window_realize_icon               (GtkWindow    *window);
 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
-static void     update_window_buttons                 (GtkWindow    *window);
+static void     update_window_actions                 (GtkWindow    *window);
 static void     get_shadow_width                      (GtkWindow    *window,
                                                        GtkBorder    *shadow_width);
 
@@ -477,6 +478,15 @@ static void        gtk_window_set_theme_variant         (GtkWindow  *window);
 static void gtk_window_activate_default_activate (GtkWidget *widget,
                                                   const char *action_name,
                                                   GVariant *parameter);
+static void gtk_window_activate_minimize (GtkWidget  *widget,
+                                          const char *action_name,
+                                          GVariant   *parameter);
+static void gtk_window_activate_toggle_maximized (GtkWidget  *widget,
+                                                  const char *name,
+                                                  GVariant   *parameter);
+static void gtk_window_activate_close (GtkWidget  *widget,
+                                       const char *action_name,
+                                       GVariant   *parameter);
 
 static void        gtk_window_do_popup                  (GtkWindow      *window,
                                                          GdkEvent       *event);
@@ -1070,6 +1080,30 @@ gtk_window_class_init (GtkWindowClass *klass)
   gtk_widget_class_install_action (widget_class, "default.activate", NULL,
                                    gtk_window_activate_default_activate);
 
+  /**
+   * GtkWindow|window.minimize:
+   *
+   * Close the window.
+   */
+  gtk_widget_class_install_action (widget_class, "window.minimize", NULL,
+                                   gtk_window_activate_minimize);
+
+  /**
+   * GtkWindow|window.toggle-maximized:
+   *
+   * Maximize or restore the window.
+   */
+  gtk_widget_class_install_action (widget_class, "window.toggle-maximized", NULL,
+                                   gtk_window_activate_toggle_maximized);
+
+  /**
+   * GtkWindow|window.close:
+   *
+   * Close the window.
+   */
+  gtk_widget_class_install_action (widget_class, "window.close", NULL,
+                                   gtk_window_activate_close);
+
   gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0,
                                        "activate-focus", NULL);
   gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0,
@@ -1662,6 +1696,30 @@ gtk_window_activate_default_activate (GtkWidget  *widget,
   gtk_window_real_activate_default (GTK_WINDOW (widget));
 }
 
+static void
+gtk_window_activate_minimize (GtkWidget  *widget,
+                              const char *name,
+                              GVariant   *parameter)
+{
+  gtk_window_minimize (GTK_WINDOW (widget));
+}
+
+static void
+gtk_window_activate_toggle_maximized (GtkWidget  *widget,
+                                      const char *name,
+                                      GVariant   *parameter)
+{
+  _gtk_window_toggle_maximized (GTK_WINDOW (widget));
+}
+
+static void
+gtk_window_activate_close (GtkWidget  *widget,
+                           const char *name,
+                           GVariant   *parameter)
+{
+  gtk_window_close (GTK_WINDOW (widget));
+}
+
 static gboolean
 gtk_window_accept_rootwindow_drop (GtkDropTargetAsync *self,
                                    GdkDrop            *drop,
@@ -2470,7 +2528,7 @@ gtk_window_set_modal (GtkWindow *window,
        gtk_grab_remove (widget);
     }
 
-  update_window_buttons (window);
+  update_window_actions (window);
 
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_MODAL]);
 }
@@ -2746,7 +2804,7 @@ gtk_window_set_transient_for  (GtkWindow *window,
        }
     }
 
-  update_window_buttons (window);
+  update_window_actions (window);
 
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_TRANSIENT_FOR]);
 }
@@ -3187,7 +3245,7 @@ gtk_window_set_decorated (GtkWindow *window,
   if (priv->surface)
     gdk_toplevel_set_decorated (GDK_TOPLEVEL (priv->surface), priv->decorated && !priv->client_decorated);
 
-  update_window_buttons (window);
+  update_window_actions (window);
   gtk_widget_queue_resize (GTK_WIDGET (window));
 
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_DECORATED]);
@@ -3246,7 +3304,7 @@ gtk_window_set_deletable (GtkWindow *window,
   if (priv->surface)
     gdk_toplevel_set_deletable (GDK_TOPLEVEL (priv->surface), priv->deletable);
 
-  update_window_buttons (window);
+  update_window_actions (window);
 
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_DELETABLE]);
 }
@@ -4104,9 +4162,17 @@ update_csd_visibility (GtkWindow *window)
 }
 
 static void
-update_window_buttons (GtkWindow *window)
+update_window_actions (GtkWindow *window)
 {
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  gboolean is_sovereign_window = !priv->modal && !priv->transient_parent;
+
+  gtk_widget_action_set_enabled (GTK_WIDGET (window), "window.minimize",
+                                 is_sovereign_window);
+  gtk_widget_action_set_enabled (GTK_WIDGET (window), "window.toggle-maximized",
+                                 priv->resizable && is_sovereign_window);
+  gtk_widget_action_set_enabled (GTK_WIDGET (window), "window.close",
+                                 priv->deletable);
 
   if (!update_csd_visibility (window))
     return;
@@ -4196,7 +4262,7 @@ create_decoration (GtkWidget *widget)
       priv->title_box = priv->titlebar;
     }
 
-  update_window_buttons (window);
+  update_window_actions (window);
 }
 
 static void
@@ -5185,10 +5251,11 @@ surface_state_changed (GtkWidget *widget)
                       GDK_SURFACE_STATE_TOP_TILED |
                       GDK_SURFACE_STATE_RIGHT_TILED |
                       GDK_SURFACE_STATE_BOTTOM_TILED |
-                      GDK_SURFACE_STATE_LEFT_TILED))
+                      GDK_SURFACE_STATE_LEFT_TILED |
+                      GDK_SURFACE_STATE_MINIMIZED))
     {
       update_window_style_classes (window);
-      update_window_buttons (window);
+      update_window_actions (window);
       gtk_widget_queue_resize (widget);
     }
 }
@@ -7022,7 +7089,7 @@ gtk_window_set_resizable (GtkWindow *window,
     {
       priv->resizable = resizable;
 
-      update_window_buttons (window);
+      update_window_actions (window);
 
       gtk_widget_queue_resize (GTK_WIDGET (window));